#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
@Author          : ricsy
@File            : html_processor.py.py
@Create Time     : 2025/6/18 04:40
@Last Modified   :
@Description     :
"""
import html
from concurrent.futures import ThreadPoolExecutor
from pathlib import Path

from bs4 import BeautifulSoup, Tag

from theme_customizer.base import BaseCustomizer


class HTMLPostProcessor(BaseCustomizer):
    """HTML 文件后处理器"""

    # 需要检查的转义字符
    TAG_CHARS = {"<", ">", "&lt;", "&gt;"}
    # 并行处理时最大线程数
    MAX_WORKERS = 4

    def apply(self):
        html_files = list(Path(self.app.outdir).rglob("*.html"))
        if not html_files:
            return
        if len(html_files) > 20:  # 文件较多时启用并行处理
            self._process_in_parallel(html_files)
        else:
            for file_path in html_files:
                self._process_file(file_path)

    def _process_in_parallel(self, file_paths: list[Path]):
        """并行处理多个文件"""
        with ThreadPoolExecutor(max_workers=self.MAX_WORKERS) as executor:
            executor.map(self._process_file, file_paths)

    def _process_file(self, file_path: Path):
        """处理单个 HTML 文件"""
        try:
            soup = self._parse_html(file_path)
            modified = False

            # 定位导航栏内的 caption
            for nav in soup.find_all("nav"):
                modified |= self._process_nav(nav)

            if modified:
                self._write_html(file_path, soup)

        except Exception as e:
            self.logger.warning(f"处理文件 {file_path} 失败: {str(e)}")

    @staticmethod
    def _parse_html(file_path: Path) -> BeautifulSoup:
        """解析 HTML 文件"""
        with open(file_path, "r", encoding="utf-8") as f:
            return BeautifulSoup(f.read(), "html.parser")

    @staticmethod
    def _write_html(file_path: Path, soup: BeautifulSoup):
        """写入处理后的 HTML"""
        with open(file_path, "w", encoding="utf-8") as f:
            f.write(str(soup))

    def _process_nav(self, nav: Tag) -> bool:
        """处理单个nav元素"""
        modified = False
        for span in nav.find_all("span", class_="caption-text"):
            if self._needs_unescape(span):
                self._unescape_span(span)
                modified = True
        return modified

    def _needs_unescape(self, span: Tag) -> bool:
        """检查是否需要解除转义"""
        # 情况1: 包含原始标签字符
        if any(char in span.get_text() for char in self.TAG_CHARS):
            return True

        # 情况2: 纯文本节点包含转义字符
        return any(
            isinstance(child, str) and any(char in child for char in self.TAG_CHARS)
            for child in span.children
        )

    @staticmethod
    def _unescape_span(span: Tag):
        """解除 span 内容转义"""
        # 解除转义并解析为新节点
        unescaped = html.unescape(str(span))
        new_span = BeautifulSoup(unescaped, "html.parser").span

        if new_span:
            # 保留原始属性和类
            new_span.attrs.update(span.attrs)

            # 特殊处理：保留 data 属性
            for attr in span.attrs:
                if attr.startswith("data-"):
                    new_span[attr] = span[attr]

            # 替换节点
            span.replace_with(new_span)
